package cn.easyutil.project.web.handler;

import cn.easyutil.project.base.bean.Page;
import cn.easyutil.project.base.bean.ResponseBody;
import cn.easyutil.util.javaUtil.JsonUtil;
import cn.easyutil.util.javaUtil.LoggerUtil;
import cn.easyutil.util.javaUtil.ObjectUtil;
import cn.easyutil.util.javaUtil.StringUtil;
import cn.easyutil.project.web.advice.ResponseOutAdvice;
import cn.easyutil.project.web.util.RequestPool;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class DefaultResponseOutAdvice implements ResponseOutAdvice {
    private static final String USER_COOKIE_NAME = "UserCookie";

    protected static final Page EMPTY_PAGE = new Page();
    protected static final Object EMPTY_OBJ = new Object();
    protected static final List EMPTY_ARRAY = new ArrayList();


    @Override
    public Object process(Object outObj, Class<?> MethodReturnType, HttpServletRequest request, HttpServletResponse response) {
        String cookieValue = String.format("SESSION=%s;path=/;HttpOnly", RequestPool.get().getSession().getId()).intern();
        response.setHeader(USER_COOKIE_NAME, cookieValue);
        if(!isToPack(outObj,MethodReturnType,request)){
            RequestPool.useResponse.remove();
            return outObj;
        }
        return pack(outObj,MethodReturnType,request);

    }

    /**
     * 对返回数据进行加密
     * @param outObj
     * @param request
     * @return
     */
    protected Object encrypt(Object outObj, HttpServletRequest request){
        String requestUrl = request.getRequestURI();
        String lastUri = requestUrl.substring(requestUrl.lastIndexOf("/") + 1);
        Object o = process2Expected(outObj, lastUri);
//        if(!o.getClass().equals(String.class)){
//            o = object2JsonString(o);
//        }
        return o;
    }

    /**
     * 是否对返回数据进行包装
     * @param outObj
     * @param MethodReturnType
     * @param request
     * @return
     */
    protected boolean isToPack(Object outObj, Class<?> MethodReturnType, HttpServletRequest request){
        if (RequestPool.useResponse.get() == null || !RequestPool.useResponse.get()) {
            return false;
        }
        if (outObj instanceof ResponseBody) {
            return false;
        }
        return true;
    }

    /**
     * 对返回数据进行包装
     * @param outObj
     * @param MethodReturnType
     * @param request
     * @return
     */
    protected Object pack(Object outObj, Class<?> MethodReturnType, HttpServletRequest request){
        if(outObj instanceof  ResponseBody){
            return outObj;
        }
        ResponseBody rb = new ResponseBody();
        rb.setCode(RequestPool.SUCCESSCODE);
        rb.setData(outObj);
        RequestPool.useResponse.remove();
        if (outObj == null) {
            if (Collection.class.isAssignableFrom(MethodReturnType)) {
                rb.setData(EMPTY_ARRAY);
                rb.setPage(EMPTY_PAGE);
            } else {
                rb.setData(EMPTY_OBJ);
            }
        }
        // 处理集合返回
        else if (outObj instanceof Collection) {
            Collection list = (Collection) outObj;
            if (!CollectionUtils.isEmpty(list)) {
                Object data = list.iterator().next();
                Page page = ObjectUtil.getAttributeValue(data, "page");
                rb.setPage(page);
                rb.setData(outObj);
            }
        }
        rb.setData(encrypt(rb.getData(),request));
        return rb;
    }

    private Object process2Expected(Object obj, String requestUrl) {
        //需要AES加密的返回数据
        if (RequestPool.ENABLE_AUTH && requestUrl.startsWith(RequestPool.ENABLE_AS_LAST_URI_PREFIX)) {
            String aesKey = RequestPool.getAESKey();
            if(!StringUtil.isEmpty(aesKey)){
                LoggerUtil.info(this.getClass(),"加密接口【"+requestUrl+"】的aesKey="+aesKey+",原始响应数据为:"+object2JsonString(obj));
                return StringUtil.AESEncode(object2JsonString(obj), aesKey);
            }
        }
        return obj;
    }

    private String object2JsonString(Object obj) {
        return JsonUtil.beanToJson(obj);
    }


}
